////////////////////////////////////////////////////////////////////////////
//
//  Crytek Engine Source File.
//  Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
//  File name:   cbuffer.h
//  Version:     v1.00
//  Created:     30/5/2002 by Vladimir Kajalin
//  Compilers:   Visual Studio.NET
//  Description: Occlusion buffer
// -------------------------------------------------------------------------
//  History:
//
////////////////////////////////////////////////////////////////////////////
#if OCCLUSIONCULLER != CCoverageBuffer
# define _CBUFFER_H
#endif
#ifndef _CBUFFER_H
#define _CBUFFER_H

#define Point2d Vec3

struct SPlaneObject
{
	Plane plane;
	Vec3_tpl<uint8> vIdx1,vIdx2;

	void Update()
	{
		//avoid breaking strict aliasing rules
		union f32_u
		{
			float floatVal;
			uint32 uintVal;
		};
		f32_u ux;	ux.floatVal = plane.n.x;
		f32_u uy;	uy.floatVal = plane.n.y;
		f32_u uz;	uz.floatVal = plane.n.z;
		uint32 bitX	=	ux.uintVal>>31;
		uint32 bitY	=	uy.uintVal>>31;
		uint32 bitZ	=	uz.uintVal>>31;
		vIdx1.x=bitX*3+0;	vIdx2.x=(1-bitX)*3+0;
		vIdx1.y=bitY*3+1;	vIdx2.y=(1-bitY)*3+1;
		vIdx1.z=bitZ*3+2;	vIdx2.z=(1-bitZ)*3+2;
	}
};

class CCoverageBuffer : public Cry3DEngineBase
{
public:
	// can be used by other classes
  static void ClipPolygon(PodArray<Vec3>& PolygonOut, const PodArray<Vec3>& pPolygon, const Plane & ClipPlane);
  static void ClipPolygon(PodArray<Vec3> * pPolygon, const Plane & ClipPlane);
  static void MatMul4( float *product, const float *a, const float *b );
  static void TransformPoint(float out[4], const float m[16], const float in[4]);

protected:

	static int ClipEdge(const Vec3 & v1, const Vec3 & v2, const Plane & ClipPlane, Vec3 & vRes1, Vec3 & vRes2);

#if defined(WIN32) && defined(_CPU_X86)
  inline int fastfround(float f) // note: only positive numbers works correct
  {
    int i;
    __asm fld [f]
    __asm fistp [i]
    return i;
  }
#else
  inline int fastfround(float f) { int i; i=(int)(f+0.5f); return i; } // note: only positive numbers works correct
#endif
};

class CPolygonClipContext
{
public:
	CPolygonClipContext();

	void Reset();

	const PodArray<Vec3>& Clip(const PodArray<Vec3>& poly, const Plane* planes, size_t numPlanes);
	const PodArray<Vec3>& Clip(const Vec3& a, const Vec3& b, const Vec3& c, const Plane* planes, size_t numPlanes);

	void GetMemoryUsage(ICrySizer * pSizer) const;

private:
	PodArray<Vec3> m_lstPolygonA;
	PodArray<Vec3> m_lstPolygonB;
};

#endif 
